home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Misc / msql-1.0.6 / src / msql / acl.c next >
C/C++ Source or Header  |  1995-02-14  |  12KB  |  788 lines

  1. /*
  2. **    acl.c    - 
  3. **
  4. **
  5. ** Copyright (c) 1993  David J. Hughes
  6. **
  7. ** Permission to use, copy, and distribute for non-commercial purposes,
  8. ** is hereby granted without fee, providing that the above copyright
  9. ** notice appear in all copies and that both the copyright notice and this
  10. ** permission notice appear in supporting documentation.
  11. **
  12. ** This software is provided "as is" without any expressed or implied warranty.
  13. **
  14. ** ID = "$Id:"
  15. **
  16. */
  17.  
  18.  
  19. #include <stdio.h>
  20. #include <sys/types.h>
  21.  
  22. #include <sys/socket.h>
  23. #include <netinet/in.h>
  24. #include <arpa/inet.h>
  25. #include <signal.h>
  26. #include <netdb.h>
  27.  
  28.  
  29. #include <common/portability.h>
  30. #include "msql_priv.h"
  31.  
  32.  
  33. #define    ALLOW    1
  34. #define REJECT    2
  35.  
  36. typedef    struct acc_s {
  37.     char    name[50];
  38.     int    access;
  39.     struct    acc_s *next;
  40. } acc_t;
  41.  
  42.  
  43. typedef struct acl_s {
  44.     char    db[NAME_LEN];
  45.     acc_t    *host,
  46.         *read,
  47.         *write;
  48.     tlist_t    *access,
  49.         *option;
  50.     struct    acl_s *next;
  51. } acl_t;
  52.  
  53.  
  54.  
  55. static acl_t    *aclHead = NULL;
  56. static int    accessPerms;
  57.  
  58. extern  char    *packet;
  59.  
  60. #define    ERR(msg)    if (verbose) printf msg 
  61.  
  62. #define    DATABASE    1
  63. #define    READ        2
  64. #define    WRITE        3
  65. #define    HOST        4
  66. #define    ACCESS        5
  67. #define OPTION        6
  68.  
  69.  
  70. static int checkToken(tok)
  71.     char    *tok;
  72. {
  73.     if (strcmp(tok,"database") == 0)
  74.         return(DATABASE);
  75.     if (strcmp(tok,"read") == 0)
  76.         return(READ);
  77.     if (strcmp(tok,"write") == 0)
  78.         return(WRITE);
  79.     if (strcmp(tok,"host") == 0)
  80.         return(HOST);
  81.     if (strcmp(tok,"access") == 0)
  82.         return(ACCESS);
  83.     if (strcmp(tok,"option") == 0)
  84.         return(OPTION);
  85.     return(-1);
  86. }
  87.  
  88.  
  89.  
  90. int msqlLoadAcl(verbose)
  91.     int    verbose;
  92. {
  93.     acl_t    *new,
  94.         *aclTail;
  95.     tlist_t    *tNew,
  96.         *tTail;
  97.     acc_t    *accNew,
  98.         *accTail;
  99.     char    buf[1024],
  100.         path[255],
  101.         *tok;
  102.     FILE    *fp;
  103.     int    newEntry,
  104.         lineNum;
  105.  
  106.  
  107.     /*
  108.     ** Open the acl file
  109.     */
  110.     (void)sprintf(path,"%s/msql.acl", msqlHomeDir);
  111.     fp = fopen(path,"r");
  112.     if (!fp)
  113.     {
  114.         if (verbose)
  115.         {
  116.             perror("Couldn't open ACL file");
  117.         }
  118.         sprintf(packet,"-1:Couldn't open ACL file\n");
  119.         return(-1);
  120.     }
  121.  
  122.  
  123.     /*
  124.     ** Process the file
  125.     */
  126.     fgets(buf,sizeof(buf),fp);
  127.     newEntry = 1;
  128.     lineNum = 1;
  129.     while(!feof(fp))
  130.     {
  131.         tok = (char *)strtok(buf," \t\n\r=,");
  132.         if (!tok)
  133.         {
  134.             /* Blank line ends a db entry */
  135.             newEntry = 1;
  136.             fgets(buf,sizeof(buf),fp);
  137.             lineNum++;
  138.             continue;
  139.         }
  140.             
  141.  
  142.         if (*tok == '#')
  143.         {
  144.             /* Comments are skipped */
  145.             fgets(buf,sizeof(buf),fp);
  146.             lineNum++;
  147.             continue;
  148.         }
  149.  
  150.  
  151.  
  152.         switch(checkToken(tok))
  153.         {
  154.             case DATABASE:
  155.             if (!newEntry)
  156.             {
  157.                 ERR(("Bad entry header location at line %d\n",
  158.                     lineNum));
  159.                 sprintf(packet,
  160.                    "-1:Bad entry header location at line %d\n"
  161.                     ,lineNum);
  162.                 return(-1);
  163.             }
  164.             newEntry = 0;
  165.             tok = (char *)strtok(NULL," \t\n\r");
  166.             if (!tok)
  167.             {
  168.                 ERR(("Missing database name at line %d\n",
  169.                     lineNum));
  170.                 printf(packet,
  171.                     "-1:Missing database name at line %d\n",
  172.                     lineNum);
  173.                 return(-1);
  174.             }
  175.             new = (acl_t *)malloc(sizeof(acl_t));
  176.             (void)bzero(new,sizeof(acl_t));
  177.             (void)strcpy(new->db,tok);
  178.             if (aclHead)
  179.             {
  180.                 aclTail->next = new;
  181.                 aclTail = new;
  182.             }
  183.             else
  184.             {
  185.                 aclHead = aclTail = new;
  186.             }
  187.             break;
  188.  
  189.  
  190.             case READ:
  191.             if (newEntry)
  192.             {
  193.                 ERR(("Bad entry header location at line %d\n",
  194.                     lineNum));
  195.                 sprintf(packet, 
  196.                     "-1:Bad entry header location at line %d\n"
  197.                     ,lineNum);
  198.                 return(-1);
  199.             }
  200.             if (new->read)
  201.             {
  202.                 accTail = new->read;
  203.                 while(accTail->next)
  204.                     accTail = accTail->next;
  205.             }
  206.             else
  207.             {
  208.                 accTail = NULL;
  209.             }
  210.             tok = (char *)strtok(NULL," \t,\n\r");
  211.             while(tok)
  212.             {
  213.                 accNew = (acc_t *)malloc(sizeof(acc_t));
  214.                 (void)bzero(accNew,sizeof(acc_t));
  215.                 if (*tok == '-')
  216.                 {
  217.                     strcpy(accNew->name,tok+1);
  218.                     accNew->access = REJECT;
  219.                 }
  220.                 else
  221.                 {
  222.                     strcpy(accNew->name,tok);
  223.                     accNew->access = ALLOW;
  224.                 }
  225.                 if (accTail)
  226.                 {
  227.                     accTail->next = accNew;
  228.                 }
  229.                 else
  230.                 {
  231.                     new->read = accNew;
  232.                 }
  233.                 accTail = accNew;
  234.                 tok = (char *)strtok(NULL," \t,\n\r");
  235.             }
  236.             break;
  237.  
  238.  
  239.             case WRITE:
  240.             if (newEntry)
  241.             {
  242.                 ERR(("Bad entry header location at line %d\n",
  243.                     lineNum));
  244.                 sprintf(packet,
  245.                     "-1:Bad entry header location at line %d\n"
  246.                     ,lineNum);
  247.                 return(-1);
  248.             }
  249.             if (new->write)
  250.             {
  251.                 accTail = new->write;
  252.                 while(accTail->next)
  253.                     accTail = accTail->next;
  254.             }
  255.             else
  256.             {
  257.                 accTail = NULL;
  258.             }
  259.             tok = (char *)strtok(NULL," \t,\n\r");
  260.             while(tok)
  261.             {
  262.                 accNew = (acc_t *)malloc(sizeof(acc_t));
  263.                 (void)bzero(accNew,sizeof(acc_t));
  264.                 if (*tok == '-')
  265.                 {
  266.                     strcpy(accNew->name,tok+1);
  267.                     accNew->access = REJECT;
  268.                 }
  269.                 else
  270.                 {
  271.                     strcpy(accNew->name,tok);
  272.                     accNew->access = ALLOW;
  273.                 }
  274.                 if (accTail)
  275.                 {
  276.                     accTail->next = accNew;
  277.                 }
  278.                 else
  279.                 {
  280.                     new->write = accNew;
  281.                 }
  282.                 accTail = accNew;
  283.                 tok = (char *)strtok(NULL," \t,\n\r");
  284.             }
  285.             break;
  286.  
  287.  
  288.             case HOST:
  289.             if (newEntry)
  290.             {
  291.                 ERR(("Bad entry header location at line %d\n",
  292.                     lineNum));
  293.                 sprintf(packet,
  294.                     "-1:Bad entry header location at line %d\n"
  295.                     ,lineNum);
  296.                 return(-1);
  297.             }
  298.             if (new->host)
  299.             {
  300.                 accTail = new->host;
  301.                 while(accTail->next)
  302.                     accTail = accTail->next;
  303.             }
  304.             else
  305.             {
  306.                 accTail = NULL;
  307.             }
  308.             tok = (char *)strtok(NULL," \t,\n\r");
  309.             while(tok)
  310.             {
  311.                 accNew = (acc_t *)malloc(sizeof(acc_t));
  312.                 (void)bzero(accNew,sizeof(acc_t));
  313.                 if (*tok == '-')
  314.                 {
  315.                     strcpy(accNew->name,tok+1);
  316.                     accNew->access = REJECT;
  317.                 }
  318.                 else
  319.                 {
  320.                     strcpy(accNew->name,tok);
  321.                     accNew->access = ALLOW;
  322.                 }
  323.                 if (accTail)
  324.                 {
  325.                     accTail->next = accNew;
  326.                 }
  327.                 else
  328.                 {
  329.                     new->host = accNew;
  330.                 }
  331.                 accTail = accNew;
  332.                 tok = (char *)strtok(NULL," \t,\n\r");
  333.             }
  334.             break;
  335.  
  336.  
  337.             case ACCESS:
  338.             if (newEntry)
  339.             {
  340.                 ERR(("Bad entry header location at line %d\n",
  341.                     lineNum));
  342.                 sprintf(packet,
  343.                     "-1:Bad entry header location at line %d\n"
  344.                     ,lineNum);
  345.                 return(-1);
  346.             }
  347.             if (new->access)
  348.             {
  349.                 tTail = new->access;
  350.                 while(tTail->next)
  351.                     tTail = tTail->next;
  352.             }
  353.             else
  354.             {
  355.                 tTail = NULL;
  356.             }
  357.             tok = (char *)strtok(NULL," \t,\n\r");
  358.             while(tok)
  359.             {
  360.                 tNew = (tlist_t *)malloc(sizeof(tlist_t));
  361.                 (void)bzero(tNew,sizeof(tlist_t));
  362.                 strcpy(tNew->name,tok);
  363.                 if (tTail)
  364.                 {
  365.                     tTail->next = tNew;
  366.                 }
  367.                 else
  368.                 {
  369.                     new->access = tNew;
  370.                 }
  371.                 tTail = tNew;
  372.                 tok = (char *)strtok(NULL," \t,\n\r");
  373.             }
  374.             break;
  375.  
  376.  
  377.             case OPTION:
  378.             if (newEntry)
  379.             {
  380.                 ERR(("Bad entry header location at line %d\n",
  381.                     lineNum));
  382.                 sprintf(packet,
  383.                     "-1:Bad entry header location at line %d\n"
  384.                     ,lineNum);
  385.                 return(-1);
  386.             }
  387.             if (new->option)
  388.             {
  389.                 tTail = new->option;
  390.                 while(tTail->next)
  391.                     tTail = tTail->next;
  392.             }
  393.             else
  394.             {
  395.                 tTail = NULL;
  396.             }
  397.             tok = (char *)strtok(NULL," \t,\n\r");
  398.             while(tok)
  399.             {
  400.                 tNew = (tlist_t *)malloc(sizeof(tlist_t));
  401.                 (void)bzero(tNew,sizeof(tlist_t));
  402.                 strcpy(tNew->name,tok);
  403.                 if (tTail)
  404.                 {
  405.                     tTail->next = tNew;
  406.                 }
  407.                 else
  408.                 {
  409.                     new->option = tNew;
  410.                 }
  411.                 tTail = tNew;
  412.                 tok = (char *)strtok(NULL," \t,\n\r");
  413.             }
  414.             break;
  415.  
  416.  
  417.             default:
  418.             ERR(("Unknown ACL command \"%s\" at line %d\n", 
  419.                 tok,lineNum));
  420.             sprintf(packet,
  421.                 "-1:Unknown ACL command \"%s\" at line %d\n", 
  422.                 tok,lineNum);
  423.             return(-1);
  424.             break;
  425.  
  426.         }
  427.  
  428.         fgets(buf,sizeof(buf),fp);
  429.         lineNum++;
  430.     }
  431. }
  432.  
  433.  
  434. dumpAcc(acc)
  435.     acc_t    *acc;
  436. {
  437.     while(acc)
  438.     {
  439.         printf("\t\t%s %s\n",(acc->access==ALLOW)?"Yes":"No ",
  440.             acc->name);
  441.         acc = acc->next;
  442.     }
  443. }
  444.  
  445.  
  446. static dumpAcl()
  447. {
  448.     acl_t    *curAcl;
  449.     tlist_t    *curT;
  450.     acc_t    *curAcc;
  451.  
  452.     curAcl = aclHead;
  453.     while(curAcl)
  454.     {
  455.         printf("\nACL's for Database %s\n",curAcl->db);
  456.         printf("\tRead access :-\n");
  457.         dumpAcc(curAcl->read);
  458.         printf("\tWrite access :-\n");
  459.         dumpAcc(curAcl->write);
  460.         printf("\tHost access :-\n");
  461.         dumpAcc(curAcl->host);
  462.  
  463.         curAcl = curAcl->next;
  464.     }
  465. }
  466.  
  467.  
  468.  
  469. static int matchToken(pattern,tok)
  470.     char    *pattern,
  471.         *tok;
  472. {
  473.     register char     *cp;
  474.     char    *buf1,
  475.         *buf2,
  476.         *cp2;
  477.     int    length1,
  478.         length2;
  479.  
  480.     /*
  481.     ** Put everything to lower case
  482.     */
  483.     buf1 = (char *)strdup(pattern);
  484.     buf2 = (char *)strdup(tok);
  485.  
  486.     cp = buf1;
  487.     while(*cp)
  488.     {
  489.         *cp = tolower(*cp);
  490.         cp++;
  491.     }
  492.  
  493.     cp = buf2;
  494.     while(*cp)
  495.     {
  496.         *cp = tolower(*cp);
  497.         cp++;
  498.     }
  499.     
  500.     /*
  501.     ** Is this a wildcard?
  502.     */
  503.     cp = pattern;
  504.     if (*cp == '*')
  505.     {
  506.         if (*(cp+1) == 0)    /* match anything */
  507.         {
  508.             return(1);
  509.         }
  510.         length1 = strlen(cp)-1;
  511.         length2 = strlen(tok);
  512.         if (length1 > length2)
  513.         {
  514.             (void)free(buf1);
  515.             (void)free(buf2);
  516.             return(0);
  517.         }
  518.         cp2 = buf2 + length2 - length1;
  519.         if (strcmp(cp+1,cp2) == 0)
  520.         {
  521.             (void)free(buf1);
  522.             (void)free(buf2);
  523.             return(1);
  524.         }
  525.         else
  526.         {
  527.             (void)free(buf1);
  528.             (void)free(buf2);
  529.             return(0);
  530.         }
  531.     }
  532.  
  533.     /*
  534.     ** OK, does the actual text match
  535.     */
  536.     if (strcmp(buf1,buf2) == 0)
  537.     {
  538.         (void)free(buf1);
  539.         (void)free(buf2);
  540.         return(1);
  541.     }
  542.     else
  543.     {
  544.         (void)free(buf1);
  545.         (void)free(buf2);
  546.         return(0);
  547.     }
  548. }
  549.  
  550.  
  551.  
  552. static int matchTextList(list,tok)
  553.     tlist_t    *list;
  554.     char    *tok;
  555. {
  556.     tlist_t    *cur;
  557.  
  558.     cur = list;
  559.     while(cur)
  560.     {
  561.         if (matchToken(cur->name, tok))
  562.         {
  563.             return(1);
  564.         }
  565.         cur = cur->next;
  566.     }
  567.     return(0);
  568. }
  569.  
  570.  
  571.  
  572. static int matchAccessList(list,tok)
  573.     acc_t    *list;
  574.     char    *tok;
  575. {
  576.     acc_t    *cur;
  577.  
  578.     cur = list;
  579.     while(cur)
  580.     {
  581.         if (matchToken(cur->name, tok))
  582.         {
  583.             if (cur->access == ALLOW)
  584.             {
  585.                 return(1);
  586.             }
  587.             else
  588.             {
  589.                 return(0);
  590.             }
  591.         }
  592.         cur = cur->next;
  593.     }
  594.     return(0);
  595. }
  596.  
  597.  
  598.  
  599. int msqlCheckAccess(db,info)
  600.     char    *db;
  601.     cinfo_t    *info;
  602. {
  603.     char     *host,
  604.         *user;
  605.     struct  sockaddr *local, 
  606.         *remote;
  607.     acl_t    *curAcl;
  608.     acc_t    *curAcc;
  609.     int    res,
  610.         perms;
  611.  
  612.  
  613.     host = info->host;
  614.     user = info->user;
  615.     local = (struct sockaddr *)&(info->local);
  616.     remote = (struct sockaddr *)&(info->remote);
  617.     
  618.     /*
  619.     ** Find an ACL entry that matches this DB
  620.     */
  621.     curAcl = aclHead;
  622.     while(curAcl)
  623.     {
  624.         if(matchToken(curAcl->db,db))
  625.         {
  626.             break;
  627.         }
  628.         curAcl = curAcl->next;
  629.     }
  630.  
  631.     if (!curAcl)
  632.     {
  633.         return(RW_ACCESS);    /* default if no specific ACL */
  634.     }
  635.  
  636.     /*
  637.     ** Now check the connection details
  638.     */
  639.     if (!host)
  640.     {
  641.         /* No host == local connection */
  642.         
  643.         if (!matchTextList(curAcl->access,"local"))
  644.         {
  645.             return(NO_ACCESS);
  646.         }
  647.     }
  648.     else
  649.     {
  650.         if (!matchTextList(curAcl->access,"remote"))
  651.         {
  652.             return(NO_ACCESS);
  653.         }
  654.         if (!matchAccessList(curAcl->host,host))
  655.         {
  656.             return(NO_ACCESS);
  657.         }
  658.     }
  659.  
  660.     /*
  661.     ** Now check the access perms
  662.     */
  663.     perms = 0;
  664.     if (matchAccessList(curAcl->read, user))
  665.     {
  666.         perms |= READ_ACCESS;
  667.     }
  668.     if (matchAccessList(curAcl->write, user))
  669.     {
  670.         perms |= WRITE_ACCESS;
  671.     }
  672.     if (perms == 0)
  673.     {
  674.         return(NO_ACCESS);
  675.     }
  676.  
  677.  
  678.     /*
  679.     ** Now perform any options for this connection
  680.     */
  681.  
  682.     
  683.     return(perms);
  684. }
  685.  
  686.  
  687.  
  688. static freeAcc(head)
  689.     acc_t    *head;
  690. {
  691.     register acc_t    *curAcc,
  692.             *prevAcc;
  693.  
  694.     curAcc = head;
  695.     while(curAcc)
  696.     {
  697.         prevAcc = curAcc;
  698.         curAcc = curAcc->next;
  699.         (void)free(prevAcc);
  700.     }
  701. }
  702.  
  703. static freeTlist(head)
  704.     tlist_t    *head;
  705. {
  706.     register tlist_t    *curText,
  707.             *prevText;
  708.  
  709.     curText = head;
  710.     while(curText)
  711.     {
  712.         prevText = curText;
  713.         curText = curText->next;
  714.         (void)free(prevText);
  715.     }
  716. }
  717.  
  718.  
  719. static freeAcls()
  720. {
  721.     register acl_t    *curAcl,
  722.             *prevAcl;
  723.  
  724.     curAcl = aclHead;
  725.     while(curAcl)
  726.     {
  727.         freeAcc(curAcl->host);
  728.         freeAcc(curAcl->read);
  729.         freeAcc(curAcl->write);
  730.         freeTlist(curAcl->access);
  731.         freeTlist(curAcl->option);
  732.         prevAcl = curAcl;
  733.         curAcl = curAcl->next;
  734.         (void)free(prevAcl);
  735.     }
  736.     aclHead = NULL;
  737. }
  738.  
  739. reloadAcls(sock)
  740.     int    sock;
  741. {
  742.     freeAcls();
  743.     msqlLoadAcl(0);
  744. }
  745.  
  746.  
  747. msqlSetPerms(perms)
  748.     int    perms;
  749. {
  750.     accessPerms = perms;
  751. }
  752.  
  753. int msqlCheckPerms(access)
  754.     int    access;
  755. {
  756.     return( accessPerms & access);
  757. }
  758.  
  759.  
  760.  
  761. int msqlCheckLocal(info)
  762.     cinfo_t    *info;
  763. {
  764.     char     *host,
  765.         *user;
  766.     struct  sockaddr *local, 
  767.         *remote;
  768.     acl_t    *curAcl;
  769.     acc_t    *curAcc;
  770.     int    res,
  771.         perms;
  772.  
  773.  
  774.     host = info->host;
  775.     user = info->user;
  776.     local = (struct sockaddr *)&(info->local);
  777.     remote = (struct sockaddr *)&(info->remote);
  778.     if ( (!info->host || strcmp(host,"localhost") == 0) &&
  779.          strcmp(info->user,ROOT) == 0)
  780.     {
  781.         return(1);
  782.     }
  783.     else
  784.     {
  785.         return(0);
  786.     }
  787. }
  788.